前面做了關於 client component 以及 server component 的基本介紹,這一篇來介紹一下他們背後的 render 機制。
server component 和 client component 會以混和渲染的方式渲染頁面。由前面介紹兩種 components 的內容可知,client component 和 server component 會交錯使用,並長成一個混和兩種元件的元件樹。
混合式渲染,橘色為 Server Components,藍色為 Client Components。資料來源: 從 Next.js 13 認識 React Server Components
當使用者初次進入網站,client 向 server 發起 request 開始,next 會初始化整個頁面架構。在這個階段,next 會透過 React api 將 server component 渲染成 React Server Component Payload (RSC Payload) 這個特殊架構。
RSC Payload 描述了整個網頁的架構,從 root 的 component 到 leaf,元件樹會被記錄在這個 payload 裡面。由於 client component 不會在 server 上執行,因此當碰到 client component 時,會先在此處記個 placeholder,代表這裡是 client component,等到後續再做渲染。
接著 next 會將 RSC Payload 和 client component 結合,生成靜態的 HTML 檔案,並將這份 html response 給 client 端。
client 端接到 html 後,會立即拿來顯示給使用者。此時在 client 的頁面是靜態,沒有互動功能的頁面,只供初次顯示使用。
接著,client 拿到 RSC Payload 後,會拿這份 RSC Payload 整合 client/server component 的元件樹,並更新 client 上的 DOM。
等到 client 端下載完 js bundle 後,便會執行 React 的 hydration,將 js code 加到 client component ,到了這個階段,網頁才有互動性。
在初次渲染後,client component 就會留在 client 端渲染,不會再由 server 生成 html 。當頁面更新時,client component 會使用 client 端的 React api 更新頁面。
server component 有三種渲染方式:
靜態渲染 static rendering
靜態渲染會是在 build time 就渲染完成,包含 data fetching、使用 server 功能等,都會在 build time 就執行完,且不會再變動。
靜態渲染是預設功能,適合那種不會因為用戶資訊變動的資料,像是 country list 等資訊就很適合。
動態渲染 dynamic rendering
動態渲染會在每一次的 request 時重新渲染,在 request time 時執行 server component 的 code,適合需要經常變動的資料,像是 user data 等。
那要怎麼使用動態渲染呢? next 會偵測資料狀態和 route 的渲染方式,檢查資料有沒有被快取、是不是 dynamic 的 route,自動切換至動態渲染。
next 有列出會動態渲染的幾種組合:
這邊另外說明一下,當 request 進來時,server component 會重新渲染,生成 RSC Payload ,再進 client 端與 client component 調和。這個階段不會重新下載 js bundle ,而是更新後的 RSC Payload 併進 client 端。
Streaming
前面有提到 code split,streaming 是類似這個功能的渲染方式,它可以提供漸進式渲染,也就是隨著使用者的瀏覽,漸進式的渲染出來。
這個功能可以利用 loading.tsx
和 React.Suspense
實作,之後會在介紹給大家。
以上,就是關於 components render 機制的介紹。相較於過去都是 client component ,內容比較複雜,學習難度較高,但同時也提升效率以及改善過去的一些痛點。
接下來會介紹 data fetch ,跟 server component 有關,請期待下一篇~